package com.mindcraft.chat.config;

import com.alibaba.fastjson.JSONObject;
import com.mindcraft.base.model.MindCraftResult;
import com.mindcraft.base.utils.JwtHelper;
import com.mindcraft.chat.message.MessageService;
import com.mindcraft.chat.po.ImChatUserMessage;
import com.mindcraft.chat.vo.ImChatUserMessageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 消息处理类
 */
@Component
@Slf4j
public class MyWsMsgHandler implements IWsMsgHandler {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MessageService messageService;

    /**
     * <li>对httpResponse参数进行补充并返回，如果返回null表示不想和对方建立连接，框架会断开连接，如果返回非null，框架会把这个对象发送给对方</li>
     * <li>注：请不要在这个方法中向对方发送任何消息，因为这个时候握手还没完成，发消息会导致协议交互失败。</li>
     * <li>对于大部分业务，该方法只需要一行代码：return httpResponse;</li>
     *
     * @param httpRequest
     * @param httpResponse
     * @param channelContext
     * @return
     * @throws Exception
     */
    @Override
    public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        // 可以在此做一些业务逻辑，返回null表示不想连接
        return httpResponse;
    }

    /**
     * 握手成功后触发该方法
     *
     * @param httpRequest
     * @param httpResponse
     * @param channelContext
     * @throws Exception
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        // 拿到用户id
        String token = httpRequest.getHeader("token");
        String userId = JwtHelper.getUserId(token);
        String userName = JwtHelper.getUserName(token);

        // 绑定用户
        Tio.bindUser(channelContext, userId);
        // 给用户发送消息
        JSONObject message = new JSONObject();
        message.put("userId", userId);
        message.put("userName", userName);
        WsResponse wsResponse = WsResponse.fromText(message.toString(), "UTF-8");
        Tio.sendToUser(channelContext.tioConfig, userId, wsResponse);
    }

    /**
     * <li>当收到Opcode.BINARY消息时，执行该方法。也就是说如何你的ws是基于BINARY传输的，就会走到这个方法</li>
     *
     * @param wsRequest
     * @param bytes
     * @param channelContext
     * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
     * @throws Exception
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        System.out.println("我走了onBytes");
        return null;
    }

    /**
     * 当收到Opcode.CLOSE时，执行该方法，业务层在该方法中一般不需要写什么逻辑，空着就好
     *
     * @param wsRequest
     * @param bytes
     * @param channelContext
     * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
     * @throws Exception
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        // 关闭连接
        Tio.remove(channelContext, "WebSocket Close");
        return null;
    }

    /**
     * <li>当收到Opcode.TEXT消息时，执行该方法。也就是说如何你的ws是基于TEXT传输的，就会走到这个方法</li>
     *
     * @param wsRequest
     * @param text
     * @param channelContext
     * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
     * @throws Exception
     */
    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        JSONObject message = JSONObject.parseObject(text);

        log.info(text);

        // 接收消息的用户ID
        String receiverId = message.getString("receiverId");
        // 获取发送消息的用户ID

        String senderId = message.getString("senderId");

        // 消息
        String msg = message.getString("msg");

        // 保存聊天记录到 Redis

        ImChatUserMessageVo chatRecord = new ImChatUserMessageVo();

        //放入实体类
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateString = LocalDateTime.now().format(formatter).replace("T", " ");
        LocalDateTime createTime = LocalDateTime.parse(dateString, formatter);
        chatRecord.setCreateTime(createTime);
        chatRecord.setContent(msg);
        String chatRecordJson = JSONObject.toJSONString(chatRecord);

        // 保存聊天记录到DB等业务逻辑...
        String hashKey = "chat:" + senderId + ":" + receiverId;
        redisTemplate.opsForList().rightPush(hashKey, chatRecordJson);
        //使用消息队列同步到数据库中

        ImChatUserMessage messageintoDB = new ImChatUserMessage();
        messageintoDB.setToId(receiverId);
        messageintoDB.setFromId(senderId);
        messageintoDB.setContent(chatRecord.getContent());

        String toDBMessage = JSONObject.toJSONString(messageintoDB);
        messageService.sendMessage(toDBMessage);


        WsResponse wsResponse = WsResponse.fromText(message.toString(), "UTF-8");
        Tio.sendToUser(channelContext.tioConfig, receiverId, wsResponse);

//        JSONObject resp = new JSONObject();
//        resp.put("msg","你好");
        return null;
    }
}